#include <iostream>
#include <vector>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include "ringqueue.hpp"
#include "Task.hpp"
#include <ctime>
using namespace std;

struct ThreadData {
    ThreadData() 
        :_rq(nullptr)
    {}
    // 构造
    ThreadData(const string& threadname, ringqueue<Task> *rq) 
        :_threadname(threadname)
        ,_rq(rq)
    {}
    string _threadname;
    ringqueue<Task> *_rq;
};










// 基于环形队列的生产者消费者模型
const string mode = "+-*/%";
void *productor(void *args) {
    ThreadData *data = static_cast<ThreadData*>(args);
    // ringqueue<Task> *rq = static_cast< ringqueue<Task>*>(args);
    while (true) {
        Task task;
        int a = rand() % 100 + 1;
        // usleep(rand() % 12);
        int b = rand() % 100;
        // usleep(rand() % 123);
        char op = mode[rand() % mode.size()];
        task._x = a;
        task._y = b;
        task._op = op;
        data->_rq->Push(task);
        cout << data->_threadname << " ";
        printf("done a equation [%d %c %d == ?]\n", task._x, task._op, task._y);

        // sleep(1);
    }
    return nullptr;
}
void *consumer(void *args) {
    ThreadData *data = static_cast<ThreadData*>(args);
    //  ringqueue<Task> *rq = static_cast< ringqueue<Task>*>(args);
    while (true) {
        // sleep(1); 
        Task task;
        data->_rq->Pop(&task);
        task.run();
        cout << data->_threadname << " ";
        printf("get result: [%d %c %d == %d](code = %d)\n", task._x, task._op, task._y, task._ret, task._code);
        // if (task._code == -1) {
        //     cerr << "error!!" << endl;
        //     exit(-1);
        // }
        sleep(1);
    }
    return nullptr;
}
int main() {
    srand(time(nullptr) ^ getpid() ^ pthread_self());
    // 创建生产者消费者线程
    pthread_t c[4], p[3];

     ringqueue<Task> *rq = new  ringqueue<Task>();
     for (int i = 0; i < 4; i++) {
        string threadname = "consumer-" + to_string(i);
        ThreadData *data = new ThreadData(threadname, rq);
        pthread_create(&c[i], nullptr, consumer, data);
     }
     for (int i = 0; i < 3; i++) {
        string threadname = "productor-" + to_string(i);
        ThreadData *data = new ThreadData(threadname, rq);
        pthread_create(&p[i], nullptr, productor, data);
     }


     for (int i = 0; i < 4; i++) {
        pthread_join(c[i], nullptr);
     }
     for (int i = 0; i < 3; i++) {
        pthread_join(p[i], nullptr);
     }


    return 0;
}